package com.yulinlin.jdbc.mysql;

import com.yulinlin.core.wrapper.*;

import java.util.Collection;

public class MysqlStringConditionWrapper<E,R> implements IStringConditionWrapper<E,R> {

    private IParamsWrapper params;

    private R endWrapper;

    private StringBuffer sql;

    private ILambdaConditionWrapper<E, IStringConditionWrapper<E, R>>  lambdaConditionWrapper;

    private boolean isNot=false;

    private boolean isAnd = true;

    private boolean openAlias = true;


    public MysqlStringConditionWrapper(R endWrapper) {
        this(endWrapper,new MysqlParamsWrapper());
    }


    public MysqlStringConditionWrapper(R endWrapper, IParamsWrapper params) {
        this.sql = new StringBuffer();
        this.params = params;
        this.endWrapper = endWrapper;
        this.lambdaConditionWrapper = new MysqlLambdaConditionWrapper(this,this);
    }

    public MysqlStringConditionWrapper(R endWrapper, IParamsWrapper params,boolean openAlias) {
        this.sql = new StringBuffer();
        this.params = params;
        this.endWrapper = endWrapper;
        this.openAlias= openAlias;
        this.lambdaConditionWrapper = new MysqlLambdaConditionWrapper(this,this);
    }

    @Override
    public IStringConditionWrapper<E,R> condition(String sql) {
        whereHandle();
        this.sql.append(" "+sql+" ");
        return this;
    }

    private String alias(String name){
        if(openAlias){
            return params.fieldToColumnName(name);
        }else{
            return name;
        }

    }

    private IStringConditionWrapper<E,R> where(String name, String condition, Object value) {
        String val ;
        if(value == null){
            val =  "";
        }else{
            val =  this.params.push(value);
        }
        String sql =alias(name)+" "+condition+" "+val+" ";
        return this.condition(sql);
    }

    //预处理
    private void whereHandle(){
        if(this.sql.length() > 0){
            if(isAnd){
                this.sql.append(" and ");
            }else{
                this.sql.append(" or ");
            }
        }
        if(isNot){
            this.sql.append(" not ");
        }
        this.isNot = false;
        this.isAnd = true;
    }


    @Override
    public IStringConditionWrapper<E,R> eq(String name, Object value) {

        return where(name," = ",value);
    }

    @Override
    public IStringConditionWrapper<E,R> ne(String name, Object value) {
        return where(name," != ",value);
    }

    @Override
    public IStringConditionWrapper<E,R> gt(String name, Number value) {
        return where(name," < ",value);
    }

    @Override
    public IStringConditionWrapper<E,R> ge(String name, Number value) {
        return where(name," <= ",value);
    }

    @Override
    public IStringConditionWrapper<E,R> lt(String name, Number value) {
        return where(name," > ",value);
    }

    @Override
    public IStringConditionWrapper<E,R> le(String name, Number value) {
        return where(name," >= ",value);
    }

    @Override
    public IStringConditionWrapper<E,R> between(String name, Object x, Object y) {

        String x1 =  this.params.push(x);
        String x2 =  this.params.push(y);
        return condition(name+" between "+ x1+" and "+x2);
    }



    @Override
    public IStringConditionWrapper<E,R> like(String name, String value) {
        return where(name," like ","%"+value +"%");
    }


    @Override
    public IStringConditionWrapper<E,R> likeLeft(String name, String value) {
        return where(name," like ","%"+value +"");
    }

    @Override
    public IStringConditionWrapper<E,R> likeRight(String name, String value) {
        return where(name," like ",""+value +"");
    }

    @Override
    public IStringConditionWrapper<E,R> isNull(String name) {
        return where(name," is null ",null);
    }



    @Override
    public IStringConditionWrapper<E,R> in(String name, Collection<?> coll) {

        StringBuffer sb =  new StringBuffer();
        for (Object row : coll){
            if(sb.length() > 0){
                sb.append(" , ");
            }
            String v =  this.params.push(row);
            sb.append(v);
        }

        return condition(name+" in ( "+sb+" ) ");
    }





    @Override
    public IStringConditionWrapper<E,R> or() {
        isAnd= false;
        return this;
    }

    @Override
    public IStringConditionWrapper<E,R> not() {
        isNot = true;
        return this;
    }




    @Override
    public String getSql() {
        return this.sql.toString();
    }

    @Override
    public R end() {
        return this.endWrapper;
    }

    public IParamsWrapper getParams() {
        return params;
    }

    public void setParams(IParamsWrapper params) {
        this.params = params;
    }


    @Override
    public ILambdaConditionWrapper<E, IStringConditionWrapper<E, R>> lambda() {
        return lambdaConditionWrapper;
    }

    @Override
    public IAbstractConditionWrapper<String, R> struct(IStructureWrapper<String, R> func) {
        whereHandle();
        this.sql.append(" ( ");
        func.run(this);
        this.sql.append(" ) ");
        return this;
    }

}
